package com.av.client.util.idioma;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.EventListener;
import java.util.EventObject;
import java.util.Properties;

import javax.swing.event.EventListenerList;

import org.apache.log4j.Logger;

import com.av.db.dataobjects.Idioma;
import com.av.exceptions.AvException;

/**
 * Clase que permite la administracion y control de idiomas
 * 
 * @author Victor J Morales R
 * 
 */
public class ManejadorIdiomas {

	private static Logger log = Logger.getLogger(ManejadorIdiomas.class);
	private static ManejadorIdiomas instance;

	protected EventListenerList listenerList = new EventListenerList();

	/**
	 * Clase creada para el manejo de eventos para el manejador de idiomas
	 * 
	 * @author Victor J Morales R
	 * 
	 */
	@SuppressWarnings("serial")
	public static class IdiomaEvent extends EventObject {
		public IdiomaEvent(Object source) {
			super(source);
		}
	}// IdiomaEvent

	/**
	 * Interfaz creada para el manejo de eventos del manejador de idiomas
	 * 
	 * @author Victor J Morales R
	 * 
	 */
	public static interface IdiomaEventListener extends EventListener {
		public void changedIdiomaEvent(IdiomaEvent evt);
	}// IdiomaEventListener

	public void addIdiomaEventListener(IdiomaEventListener listener) {
		listenerList.add(IdiomaEventListener.class, listener);
	}// addIdiomaEventListener

	public void removeIdiomaEventListener(IdiomaEventListener listener) {
		listenerList.remove(IdiomaEventListener.class, listener);
	}// removeIdiomaEventListener

	void fireIdiomaEvent(IdiomaEvent evt) {
		Object[] listeners = listenerList.getListenerList();
		// Each listener occupies two elements - the first is the listener class
		// and the second is the listener instance
		for (int i = 0; i < listeners.length; i += 2) {
			if (listeners[i] == IdiomaEventListener.class) {
				((IdiomaEventListener) listeners[i + 1])
						.changedIdiomaEvent(evt);
			}
		}
	}// fireIdiomaEvent

	private Properties etiquetas = new Properties();
	private Properties errores = new Properties();
	private Idioma idioma;

	private File avArchivo = new File(System.getProperties().getProperty(
			"java.io.tmpdir")
			+ File.separator + "av.properties");
	private Properties avPropiedades = new Properties();

	public static ManejadorIdiomas getInstance() {
		log.info("Inicio - getInstance()");

		if (instance == null) {
			instance = new ManejadorIdiomas();
		}

		log.info("Fin - getInstance()");

		return instance;
	}// getInstance

	private ManejadorIdiomas() {
		log.info("Inicio - ctor()");
		cargarPropiedades();
		log.info("Fin - ctor()");
	}// Idioma

	/**
	 * Funcion que la traduccion de la etiqueta solicitada
	 * 
	 * @param key
	 *            Etiqueta solicitada
	 * @return Etiqueta traducida
	 * @throws AvException
	 *             En caso de que no se haya previamente cargado los valores
	 */
	public String obtenerEtiqueta(Etiqueta etiqueta) {
		log.info("Inicio - obtenerEtiqueta(Etiqueta etiqueta)");

		if (etiquetas == null) {
			log.error("No se han cargado las propiedades para el idioma");
			return null;
		}

		log.info("Fin - obtenerEtiqueta(Etiqueta etiqueta)");

		return etiquetas.getProperty(etiqueta.getKey());
	}// obtenerEtiqueta

	/**
	 * Funcion que obtiene la traduccion del error solicitado
	 * 
	 * @param error
	 * @return
	 */
	public String obtenerError(Error error) {
		log.info("Inicio - obtenerError(Error error)");

		if (errores == null) {
			log.error("No se han cargado las propiedades para el idioma");
			return null;
		}

		log.info("Fin - obtenerError(Error error)");

		return errores.getProperty(error.getKey());

	}

	/**
	 * Obtiene el idioma actual con el cual trabaja el sistema
	 * 
	 * @return
	 */
	public Idioma getIdioma() {
		return this.idioma;
	}// getIdioma

	/**
	 * Asigna el idioma a obtener sus propiedades
	 * 
	 * @param idioma
	 */
	public void setIdioma(Idioma idioma) {
		if (!this.idioma.equals(idioma)) {
			this.idioma = idioma;
			cargarPropiedades();
			guardarIdioma();
			fireIdiomaEvent(new IdiomaEvent(idioma));
		}
	}// setIdioma

	/**
	 * Funcion que carga las propiedades a partir de un archivo de configuracion
	 */
	private void cargarPropiedades() {
		log.info("Inicio - cargarPropiedades()");

		if (idioma == null) {
			cargarIdiomaDesdeArchivo();
		}

		try {
			etiquetas.load(new FileInputStream(new File(idioma
					.obtenerRutaAbsoluta())));
			errores.load(new FileInputStream(new File(idioma
					.obtenerRutaAbsolutaArchivoError())));
		} catch (FileNotFoundException e) {
			log.error("No se encontro el archivo de idiomas");
		} catch (IOException e) {
			log.error("Problemas al cargar los valores para los idiomas");
		}

		log.info("Fin - cargarPropiedades()");
	}// cargarPropiedades

	/**
	 * Funcion que obtiene el idioma previamente guardado en el archivo local o
	 * en caso de no existir usa el idioma por defecto para el sistema
	 * 
	 * @return Idioma guardado localmente o, en caso de no existir, el idioma
	 *         por defecto
	 */
	private void cargarIdiomaDesdeArchivo() {
		log.info("Inicio - cargarIdiomaDesdeArchivo()");

		if (avArchivo.exists() && avArchivo.canRead()) {
			try {
				avPropiedades.load(new FileInputStream(avArchivo));
				idioma = Idioma.getIdioma(Integer.parseInt(avPropiedades
						.getProperty("idioma")));
			} catch (FileNotFoundException e) {
				log.error("No se encontro el archivo de configuracion");
				idioma = Idioma.getDefault();
			} catch (IOException e) {
				log.error("Problemas al cargar la configuracion");
				idioma = Idioma.getDefault();
			}
		} else if (!avArchivo.exists()) {
			idioma = Idioma.getDefault();
			guardarIdioma();
		} else {
			log.error("No se tienen permisos sobre el archivo");
		}

		log.info("Fin - cargarIdiomaDesdeArchivo()");
	}// cargarIdiomaDesdeArchivo

	/**
	 * Funcion que guarda el idioma seleccionado por el usuario
	 */
	private void guardarIdioma() {
		log.info("Inicio - guardarIdioma()");

		FileOutputStream fosAVSettings = null;

		if (avPropiedades != null) {
			avPropiedades.setProperty("idioma", idioma.getId() + "");
			try {
				fosAVSettings = new FileOutputStream(avArchivo);
			} catch (FileNotFoundException e) {
				log.error("No se encontro el archivo de configuracion");
			}
			try {
				avPropiedades.store(fosAVSettings,
						"# Preferencias Iniciales del sistema.");
				fosAVSettings.flush();
				fosAVSettings.close();
			} catch (IOException e) {
				log.error("Problemas al guardar las preferencias");
			}
		}

		log.info("Fin - guardarIdioma()");
	}// guardarIdioma
}// ManejadorIdiomas